/** **************************************************
 * Description: DAO的默认实现类
 * Copyright:   Copyright (c) 2008
 * Company:    cl
 * @author     caoxl
 * @version    1.0
 * @see
 HISTORY
 *  2008-7-1 caoxl Create File
 ************************************************* */
package com.bfsuolframework.core.dao;

import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.LockOptions;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.sql.JoinType;
import org.hibernate.type.IntegerType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.DataAccessException;

import com.bfsuolframework.core.configuration.ConfigUtils;
import com.bfsuolframework.core.controller.support.Pagination;
import com.bfsuolframework.core.controller.support.QueryParam;
import com.bfsuolframework.core.dao.support.HqlParameter;
import com.bfsuolframework.core.entity.Entity;

public class HibernateDAOSupport<E extends Entity> implements DAO<E> {
	/**
	 * Logger for this class
	 */
	protected final Logger logger = Logger.getLogger(getClass());
	
	@Autowired
	@Qualifier("sessionFactory")
	private SessionFactory sessionFactory;

	public Session getSession() {
		// 事务必须是开启的(Required)，否则获取不到
		return sessionFactory.getCurrentSession();
	}
	
	@SuppressWarnings("rawtypes")
	private Class entityClass;
	//private static final int BATCH_SIZE = ConfigUtils.getInt("sys.BATCH_SIZE", 20);
	
	
	public HibernateDAOSupport(){
		entityClass =(Class<?>)((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
	}
	
	public Long save(final E entity) {
		try {
			Session session = getSession();
			Long id = (Long)session.save(entity);
			session.flush();
			if (logger.isDebugEnabled()) {
				logger.debug("保存实体成功：" + entity.toString());
			}
			return id;
		} catch (RuntimeException e) {
			logger.error("保存实体异常", e);
			throw e;
		}
	}

	public void update(final E entity) {
		try {
			Session session = getSession();
			session.update(entity);
			session.flush();
			if (logger.isDebugEnabled()) {
				logger.debug("更新实体成功：" + entity.toString());
			}
		} catch (RuntimeException e) {
			logger.error("保存实体异常", e);
			throw e;
		}
	}
	
	public Long saveOrUpdate(final E entity) {
		try {
			Session session = getSession();
			Long id = 0L;
			if(Entity.class.isAssignableFrom(this.entityClass)){
				Entity e = (Entity)entity;
				if(e.isNew()){
					id = (Long)session.save(entity);
					session.flush();
				}else{
					session.update(entity);
					session.flush();
					id = e.getId();
				}
			}else{
				session.saveOrUpdate(entity);
				session.flush();
			}
			if (logger.isDebugEnabled()) {
				logger.debug("保存或者更新实体成功：" + entity.toString());
			}
			return id;
		} catch (RuntimeException e) {
			logger.error("保存实体异常", e);
			throw e;
		}
	}
	
	public void merge(final E entity) {
		try {
			getSession().merge(entity);
			if (logger.isDebugEnabled()) {
				logger.debug("合并实体成功：" + entity.toString());
			}
		} catch (RuntimeException e) {
			logger.error("合并实体异常", e);
			throw e;
		}
	}

	public E getById(final Long id) {
		return getById(id, LockOptions.NONE);
	}
	
	@SuppressWarnings("unchecked")
	public E getById(final Long id,LockOptions lock) {
		return (E)getSession().get(entityClass, id, lock);
	}
	
	public E loadById(final Long id) {
		return loadById(id, LockOptions.NONE);
	}
	
	@SuppressWarnings("unchecked")
	public E loadById(final Long id,LockOptions lock) {
		return (E)getSession().load(entityClass, id, lock);
	}
	
	public void delete(final E obj) {
		getSession().delete(obj);
	}
	
	public void delete(final Long id) {
		this.executeHql("delete " + entityClass.getName() + " e where e.id=:id", HqlParameter.newInstance("id", id));
	}


	public void evict(final E obj) {
		getSession().evict(obj);
	}
	
	public void flush() {
        try {
        	getSession().flush();
        } catch (DataAccessException e) {
            if(logger.isDebugEnabled()){
            	logger.debug(e);
            }
        }
    }
	
	public void clear(){
		getSession().clear();
	}
	
	public void batchSave(final List<E> entities) {
		try {
			if (entities == null) {
				return;
			}
			Session session = getSession();
			int index = 0;
			int BATCH_SIZE = ConfigUtils.getInt("sys.BATCH_SIZE", 20);
			for (E e : entities) {
				session.save(e);
				index++;
				if ((index % BATCH_SIZE == 0)) {
					session.flush();
					session.clear();
				}
			}
			session.flush();
		} catch (DataAccessException e) {
			if (logger.isDebugEnabled()) {
				logger.debug(e);
			}
		}
	}

	public void batchUpdate(final List<E> entities) {
		try {
			if (entities == null) {
				return;
			}
			Session session = getSession();
			int index = 0;
			int BATCH_SIZE = ConfigUtils.getInt("sys.BATCH_SIZE", 20);
			for (E e : entities) {
				session.update(e);
				index++;
				if ((index % BATCH_SIZE == 0)) {
					session.flush();
					session.clear();
				}
			}
			session.flush();
		} catch (DataAccessException e) {
			if (logger.isDebugEnabled()) {
				logger.debug(e);
			}
		}
	}
    
    public void batchSaveOrUpdate(final List<E> entities){
    	try {
			if (entities == null) {
				return;
			}
			Session session = getSession();
			int index = 0;
			int BATCH_SIZE = ConfigUtils.getInt("sys.BATCH_SIZE", 20);
			for (E e : entities) {
				session.saveOrUpdate(e);
				index++;
				if ((index % BATCH_SIZE == 0)) {
					session.flush();
					session.clear();
				}
			}
			session.flush();
		} catch (DataAccessException e) {
			if (logger.isDebugEnabled()) {
				logger.debug(e);
			}
		}
    }
    
    public void batchRemove(final List<E> entities){
    	try {
			if (entities == null) {
				return;
			}
			Session session = getSession();
			int index = 0;
			int BATCH_SIZE = ConfigUtils.getInt("sys.BATCH_SIZE", 20);
			for (E e : entities) {
				session.refresh(e);
				session.delete(e);
				index++;
				if ((index % BATCH_SIZE == 0)) {
					session.flush();
					session.clear();
				}
			}
			session.flush();
		} catch (DataAccessException e) {
			if (logger.isDebugEnabled()) {
				logger.debug(e);
			}
		}
    }

	
	/**
	 * *********************************************************************************************************
	 * 通过sql进行数据库的操作
	 */
	protected int getCountBySQL(final String sql) {
        SQLQuery query = getSession().createSQLQuery(sql).addScalar("RecCount",IntegerType.INSTANCE);
        Integer count = (Integer)query.uniqueResult();
        return count == null ? 0 : count.intValue();
    }

	protected List<E> findAllBySQL(final String sql) {
		return findAllBySQL(sql, null, null, -1, -1);
	}
	 
	protected List<E> findAllBySQL(final String sql, final int startIndex, final int maxResultCount) {
		return findAllBySQL(sql, null, null, startIndex, maxResultCount);
	}

	protected List<E> findAllBySQL(final String sql, final String alias) {
		return findAllBySQL(sql, null, alias, -1, -1);
	}
	
	protected List<E> findAllBySQL(final String sql, final String alias, final int startIndex, final int maxResultCount) {
		return findAllBySQL(sql, null, alias, startIndex, maxResultCount);
	}
	
	protected List<E> findAllBySQL(final String sql, final Object[] params) {
		return findAllBySQL(sql, params, null, -1, -1);
	}
	
	protected List<E> findAllBySQL(final String sql, final Object[] params, final int startIndex, final int maxResultCount) {
		return findAllBySQL(sql, params, null, startIndex, maxResultCount);
	}
	
	@SuppressWarnings("unchecked")
	protected List<E> findAllBySQL(final String sql, final Object[] params, final String alias, final int startIndex, final int maxResultCount) {
		SQLQuery query = getSession().createSQLQuery(sql);
		if(entityClass != null){
			if(alias != null && !alias.equals("")){
				query.addEntity(alias, entityClass);
			}else{
				query.addEntity(entityClass);
			}
		}
		if(params != null && params.length > 0){
			int index = 0;
			for(Object p : params){
				query.setParameter(index, p);
			}
		}
		if (maxResultCount > 0)
			query.setMaxResults(maxResultCount);
		if (startIndex > 0)
			query.setFirstResult(startIndex);
		return query.list();
	}
	
	@SuppressWarnings("unchecked")
	protected <T> List<T> findEntitiesBySQL(final String sql, final Object[] params, final String alias,Class<T> entityClass,  final int startIndex, final int maxResultCount) {
		SQLQuery query = getSession().createSQLQuery(sql);
		if(entityClass != null){
			if(alias != null && !alias.equals("")){
				query.addEntity(alias, entityClass);
			}else{
				query.addEntity(entityClass);
			}
		}
		if(params != null && params.length > 0){
			int index = 0;
			for(Object p : params){
				query.setParameter(index, p);
			}
		}
		if (maxResultCount > 0)
			query.setMaxResults(maxResultCount);
		if (startIndex > 0)
			query.setFirstResult(startIndex);
		return query.list();
	}
	
	@SuppressWarnings("rawtypes")
	protected List findObjectsBySQL(final String sql, final Object[] params) {
		return findObjectsBySQL(sql, params, -1, -1);
	}
	
	@SuppressWarnings("rawtypes")
	protected List findObjectsBySQL(final String sql, final int startIndex, final int maxResultCount) {
		return findObjectsBySQL(sql, null, startIndex, maxResultCount);
	}
	
	@SuppressWarnings("rawtypes")
	protected List findObjectsBySQL(final String sql, final Object[] params, final int startIndex, final int maxResultCount) {
		SQLQuery query = getSession().createSQLQuery(sql);
		if(params != null && params.length > 0){
			int index = 0;
			for(Object p : params){
				query.setParameter(index, p);
			}
		}
		if (maxResultCount > 0)
			query.setMaxResults(maxResultCount);
		if (startIndex > 0)
			query.setFirstResult(startIndex);
		return query.list();
	}
	
	protected int executeSql(final String sql) {
		return executeSql(sql,null);
	}
	
	protected int executeSql(final String sql, Object[] params) {
		SQLQuery query = getSession().createSQLQuery(sql);
		if(params != null && params.length > 0){
			int index = 0;
			for(Object p : params){
				query.setParameter(index, p);
				index++;
			}
		}
		return query.executeUpdate();
	}

	/**
	 * ****************************************************************************************************
	 * 通过Hql进行数据库操作
	 * @param hql
	 * @param parameters
	 * @param page
	 * @return
	 */
	public Pagination getPage(final String hql,final HqlParameter parameters,final Pagination page) {
		page.setTotalRecord(getCount(getHqlforCount(hql),parameters));
		if(logger.isDebugEnabled()){
			logger.debug("totalRecord=" + page.getTotalRecord());
			logger.debug("page.getCurrentPage()="+ page.getCurrentPage() +",page.getTotalRecord()="+page.getTotalRecord() +",page.getTotalPage()="+page.getTotalPage() +",page.getStartRecord()="+page.getStartRecord());
		}
		//dc.setProjection(null);
		//dc.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
		@SuppressWarnings("rawtypes")
		List list = findAll(hql, parameters, page.getStartRecord()-1,page.getPageSize());
		if(logger.isDebugEnabled()){
			logger.debug("list.size()=" + list.size());
		}
		page.setItems(list);
		return page;
	}
	
	protected int executeHql(final String hql){
		return executeHql(hql,null);
    }
	
	protected int executeHql(final String hql, final HqlParameter parameters) {
		Query query = getSession().createQuery(hql);
		query = getQueryWithParameter(query, parameters);
		return query.executeUpdate();
	}
	
    @SuppressWarnings("unchecked")
	protected E getByHql(final String hql,final HqlParameter parameters){
		Query query = getSession().createQuery(hql);
		query = getQueryWithParameter(query, parameters);
		List<E> list = query.list();
		return (list == null || list.isEmpty()) ? null : list.get(0);
    }
    
	@SuppressWarnings("unchecked")
	public List<E> findAll() {
		return getSession().createQuery("from " + entityClass.getName()).list();
	}
	
	protected List<E> findAll(final String hql) {
		return findAll(hql,-1,-1);
	}
	
	protected List<E> findAll(final String hql,final int startIndex, final int maxResultCount) {
		 return findAll(hql,null,startIndex,maxResultCount);
	}
	
	protected List<E> findAll(final String hql,final HqlParameter parameters) {
		return findAll(hql,parameters,-1,-1);
	}
	
	@SuppressWarnings("unchecked")
	protected List<E> findAll(final String hql,final HqlParameter parameters, final int startIndex, final int maxResultCount) {
		Query query = getSession().createQuery(hql);
		query = getQueryWithParameter(query, parameters);
		if (maxResultCount > 0)
			query.setMaxResults(maxResultCount);
		if (startIndex > 0)
			query.setFirstResult(startIndex);
		return query.list();
	}
	protected List findObjectsAll(final String hql,final HqlParameter parameters) {
		return findObjectsAll(hql,parameters,-1,-1);
	}
	
	@SuppressWarnings("unchecked")
	protected List findObjectsAll(final String hql,final HqlParameter parameters, final int startIndex, final int maxResultCount) {
		Query query = getSession().createQuery(hql);
		query = getQueryWithParameter(query, parameters);
		if (maxResultCount > 0)
			query.setMaxResults(maxResultCount);
		if (startIndex > 0)
			query.setFirstResult(startIndex);
		return query.list();
	}
	protected int getCount(final String hql) {
		return getCount(hql,null);
	}
	
	protected int getCount(final String hql, final HqlParameter parameters) {
		Query query = getSession().createQuery(hql);
		query = getQueryWithParameter(query, parameters);
		Long count = (Long) query.uniqueResult();
		return count == null ? 0 : count.intValue();
	}
	
	protected  Query getQueryWithParameter(Query query,HqlParameter parameters){
		if(parameters != null && !parameters.isEmpty()){
			for(HqlParameter.Parameter param:parameters.getParameters()){
				switch(param.getType()){
					case HqlParameter.STRING:
						query.setString(param.getKey(), param.getStringValue());
					 	break;
					case HqlParameter.INT:
					 	query.setInteger(param.getKey(), param.getIntValue());
					 	break;
					case HqlParameter.BOOLEAN:
						query.setBoolean(param.getKey(), param.getBooleanValue());
					 	break;
					case HqlParameter.DATE:
						query.setDate(param.getKey(), param.getDateValue());
					 	break;
					case HqlParameter.FLOAT:
					 	query.setFloat(param.getKey(), param.getFloatValue());
					 	break;
					case HqlParameter.DOUBLE:
					 	query.setDouble(param.getKey(), param.getDoubleValue());
					 	break;
					case HqlParameter.LONG:
					 	query.setLong(param.getKey(), param.getLongValue());
				}
			}
			if(this.logger.isDebugEnabled()){
				StringBuilder builder = new StringBuilder("HqlParameter:");
				for(HqlParameter.Parameter param:parameters.getParameters()){builder.append(param.getKey()).append(":").append(param.getValue()).append(";");}
				logger.debug(builder.toString());
			}
		}
		return query;
	}
	protected  String removeSelect(String sql) {
		if(sql==null || sql.equals("")){
			return "";
		}
		int beginPos = sql.toLowerCase().indexOf("from");
		if(beginPos == -1){
			return sql;
		}
		return sql.substring(beginPos);
	}

	protected  String getHqlforCount(String hql){
		return "SELECT COUNT(*) " + removeSelect(hql);
	}
	
	/**
	 * **********************************************************************************************
	 * 通过Criteria进行数据苦操作
	 */
	
	public Pagination getPage(final QueryParam query, final Pagination page) {
		Criteria criteria = getSession().createCriteria(entityClass);
		getCriteria(criteria, query);

		// 得到数量
		page.setTotalRecord(getCount(criteria));
		// 去除Projection，返回对象
		criteria.setProjection(null);

		if (query.isDistinct()) {
			criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
		} else {
			criteria.setResultTransformer(Criteria.ROOT_ENTITY);
		}

		List<E> list = findAll(criteria, page.getStartRecord() - 1,
				page.getPageSize());
		page.setItems(list);

		return page;

	}
	
	public List<E> findAll(final QueryParam query) {
		return findAll(query, -1, -1);
	}

	public List<E> findAll(final QueryParam query, final int firstResult, final int maxResult) {
		Criteria criteria = getSession().createCriteria(entityClass);
		getCriteria(criteria, query);

		criteria.setProjection(null);

		if (query.isDistinct()) {
			criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
		} else {
			criteria.setResultTransformer(Criteria.ROOT_ENTITY);
		}
		return findAll(criteria, firstResult, maxResult);
	}
	
	@SuppressWarnings("unchecked")
	public List<E> findAll(Criteria criteria, int firstResult, int maxResult) {
		
		if(firstResult>0){
			criteria.setFirstResult(firstResult);
		}
		if(maxResult>0){
			criteria.setMaxResults(maxResult);
		}
		return criteria.list();
	}
	
	public int getCount(final QueryParam query) {
		Criteria criteria = getSession().createCriteria(entityClass);
		criteria = getCriteria(criteria, query);
		return getCount(criteria);
	}
	
	public int getCount(Criteria criteria) {
		Long count = (Long) criteria.setProjection(Projections.rowCount()).uniqueResult();
		return count == null ? 0 : count.intValue();
	}

	/**
	 * 判断属性有无相同的值，用作更新
	 * @param propertyName 属性名称
	 * @param value 判断的值
	 * @param excludePrimaryKey 排除的主键
	 * @return
	 */
	public boolean isPropertyUnique(final String propertyName,
			final Object value, final Long excludePrimaryKey) {
		if (propertyName == null || propertyName.equals("")) {
			return false;
		}
		if (value == null) {
			return true;
		}

		Criteria criteria = getSession().createCriteria(entityClass);
		criteria.add(Restrictions.eq(propertyName, value));
		if (excludePrimaryKey != null && excludePrimaryKey.longValue() > 0) {
			criteria.add(Restrictions.not(Restrictions.eq("id",
					excludePrimaryKey)));
		}
		return getCount(criteria) == 0;
	}
	
	/**
	 * 判断属性有无相同的值，用作更新
	 * @param propertyName 属性名称
	 * @param value 判断的值
	 * @param excludePrimaryKey 排除的主键
	 * @param includecColumn 所在的列
	 * @param includecColumnValue 所在列判断的值
	 * @return
	 */
	public boolean isPropertyUnique(final String propertyName,
			final Object value, final Long excludePrimaryKey,
			final String includecColumn, final Long includecColumnValue) {
		if (propertyName == null || propertyName.equals("")) {
			return false;
		}
		if (value == null) {
			return true;
		}

		Criteria criteria = getSession().createCriteria(entityClass);
		criteria.add(Restrictions.eq(propertyName, value));
		if (excludePrimaryKey != null && excludePrimaryKey.longValue() > 0) {
			criteria.add(Restrictions.not(Restrictions.eq("id",
					excludePrimaryKey)));
		}
		if (includecColumn != null && !"".equals(includecColumn)
				&& null != includecColumnValue
				&& includecColumnValue.longValue() > 0) {
			criteria.add(Restrictions.eq(includecColumn, includecColumnValue));
		}
		return getCount(criteria) == 0;
	}

	protected Criteria getCriteria(Criteria criteria,QueryParam query){
		
		if(query.hasQuerys()){
			List<String> aliases = new ArrayList<String>();
			for(QueryParam.QueryElement element : query.getQuerys()){
				//判断是否是or的组
				if(element.hasOrQuerys()){
					if(logger.isDebugEnabled()){
						logger.debug("Hibernate:Add OR Query:" 
								+"key="+element.getKey()
								+";value="+element.getValue()
								+";convertedValue="+element.getConvertedValue()
								+";group="+element.getGroupName()
								+";operator="+element.getOperatorString()
								+";type="+element.getTypeString()
								+";method="+element.getMethod());
					}
					Disjunction disjunction = Restrictions.disjunction();
					disjunction.add(getCriterion(generateAlias(criteria, element.getMethod(), aliases),element));
					for(QueryParam.QueryElement or : element.getOrQuerys()){
						if(logger.isDebugEnabled()){
							logger.debug("Hibernate:Add OR2 Query:" 
									+"key="+or.getKey()
									+";value="+or.getValue()
									+";convertedValue="+or.getConvertedValue()
									+";group="+or.getGroupName()
									+";operator="+or.getOperatorString()
									+";type="+or.getTypeString()
									+";method="+or.getMethod());
						}
						disjunction.add(getCriterion(generateAlias(criteria, or.getMethod(), aliases),or));
					}
					criteria.add(disjunction);
				}else{
					if(logger.isDebugEnabled()){
						logger.debug("Hibernate:Add AND Query:" 
								+"key="+element.getKey()
								+";value="+element.getValue()
								+";convertedValue="+element.getConvertedValue()
								+";group="+element.getGroupName()
								+";operator="+element.getOperatorString()
								+";type="+element.getTypeString()
								+";method="+element.getMethod());
					}
					criteria.add(getCriterion(generateAlias(criteria, element.getMethod(), aliases),element));
				}
			}
		}
		
		if(query.hasOrders()){
			for(QueryParam.OrderElement order:query.getOrders()){
				if(logger.isDebugEnabled()){
					logger.debug("Add Order, Colum is:" + order.getField() + ", ASC is:" + order.isAsc());
				}
				if(order.isAsc()){
					criteria.addOrder(Order.asc(order.getField()));
				}else{
					criteria.addOrder(Order.desc(order.getField()));
				}
			}
		}else{
			//如果没有加入排序字段，则自动加入按照主键排序
			criteria.addOrder(Order.desc("id"));
		}
		
		if(query.isDistinct()){
			criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); 
		}else{
			criteria.setResultTransformer(Criteria.ROOT_ENTITY);
		}
		
		return criteria;
	}
	
	/**
	 * 处理查询条件，生成对应的Criterion对象
	 * @param key
	 * @param query
	 * @return
	 */
	protected Criterion getCriterion(String key, QueryParam.QueryElement query){
		switch(query.getOperator()){
			case EQUAL:
				return Restrictions.eq(key, query.getConvertedValue());
			case LIKE:
				return Restrictions.like(key, "%"+query.getConvertedValue()+"%");
			case LIKE_LEFT:
				return Restrictions.like(key, "%"+query.getConvertedValue());
			case LIKE_RIGHT:
				return Restrictions.like(key, query.getConvertedValue()+"%");
			case GREAT:
				return Restrictions.gt(key, query.getConvertedValue());
			case LESS:
				return Restrictions.lt(key, query.getConvertedValue());
			case GREAT_EQUAL:
				return Restrictions.ge(key, query.getConvertedValue());
			case LESS_EQUAL:
				return Restrictions.le(key, query.getConvertedValue());
			case NOT_EQUAL:
				return Restrictions.not(Restrictions.eq(key, query.getConvertedValue()));
			case IS_NULL:
				return Restrictions.isNull(key);
			case NOT_NULL:
				return Restrictions.isNotNull(key);
		}
		return Restrictions.eq(key, query.getConvertedValue());
	}
	
	/**
	 * 处理Alias问题
	 * name的格式是 group|g.name   group  g别名  name属性   
	 * 返回g.name
	 * 
	 * key  === group
	 * trueName === g.name
	 * aligs  === g
	 * 
	 */
	protected String generateAlias(Criteria criteria,String name,List<String> aliases){
		int aliasPos = name.indexOf("|");
		if(aliasPos < 0){
			return name;
		}
		JoinType joinType = name.charAt(aliasPos - 1) == '[' ? 
				(name.charAt(aliasPos + 1) == ']' ? JoinType.FULL_JOIN : JoinType.LEFT_OUTER_JOIN) 
				: 
				(name.charAt(aliasPos + 1) == ']' ? JoinType.RIGHT_OUTER_JOIN : JoinType.INNER_JOIN);
		String key = (joinType == JoinType.LEFT_OUTER_JOIN) ? name.substring(0,aliasPos-1) : name.substring(0,aliasPos);
		String trueName = (joinType == JoinType.FULL_JOIN || joinType == JoinType.RIGHT_OUTER_JOIN) ? name.substring(aliasPos + 2) : name.substring(aliasPos + 1);
		
		if (trueName.indexOf(".") == -1) {
			return trueName;
		}
		String alias = trueName.substring(0,trueName.indexOf("."));
		if (aliases == null) {
			aliases = new ArrayList<String>();
		}
		
		if (!aliases.contains(alias)) {
			criteria = criteria.createAlias(key, alias, joinType);
			aliases.add(alias);
		}
		
		//递归调用
		return generateAlias(criteria, trueName, aliases);
	}
	
}
